package com.cn.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;

@Slf4j
public class NioServer4 {

  public static void main(String[] args) throws IOException {
    Selector selector = null;
    try {
      selector = Selector.open();
    } catch (IOException e) {
      e.printStackTrace();
    }

    /*
     *创建一个 channel 连接
     */
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.bind(new InetSocketAddress(8080));
    serverSocketChannel.configureBlocking(false);
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    //在当前线程轮询
    while (true) {
      int select = selector.select();
      Set<SelectionKey> selectionKeys = selector.selectedKeys();

      Iterator<SelectionKey> iterator = selectionKeys.iterator();
      while (iterator.hasNext()) {
        SelectionKey selectionKey = iterator.next();
        iterator.remove();

        log.debug("SelectionKey {}", selectionKey);

        if (selectionKey.isAcceptable()) {
          ServerSocketChannel newServerSocketChannel
                  = (ServerSocketChannel) selectionKey.channel();

          SocketChannel accept = newServerSocketChannel.accept();
          accept.configureBlocking(false);
          SelectionKey selectionKey1 = accept.register(selector, SelectionKey.OP_READ);
        } else if (selectionKey.isReadable()) {
          SocketChannel socketChannel =
                  (SocketChannel) selectionKey.channel();
          log.info("isReadable done -> {}", socketChannel);
          ByteBuffer buffer = ByteBuffer.allocate(1024);
          socketChannel.read(buffer);
          String request = new String(buffer.array());
          log.info("request -> {}", request);
          SelectionKey selectionKey1 = socketChannel.register(selector, SelectionKey.OP_WRITE, request);
        } else if (selectionKey.isWritable()) {
          SocketChannel socketChannel =
                  (SocketChannel) selectionKey.channel();
          log.info("isWritable done -> {}", socketChannel);
//
//          String request = (String) selectionKey.attachment(); //获取客户端的请求
//          log.info("对 客服端 消息 -> {} 做应答 ", request);
//          // 写入
//          ByteBuffer buffer = ByteBuffer.allocate(1024);
//          buffer.put("i`m server".getBytes());
//          buffer.flip();
//
//          socketChannel.write(buffer);
//          socketChannel.close();

          //回调
          Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String request) {
              log.info("socketChannel -> {}", socketChannel);
              // 写入
              ByteBuffer buffer = ByteBuffer.allocate(1024);
              buffer.put(request.getBytes());
              buffer.flip();
              try {
                socketChannel.write(buffer);
              } catch (IOException e) {
                e.printStackTrace();
              }finally {
                try {
                  socketChannel.close();
                } catch (IOException e) {
                  e.printStackTrace();
                }
              }
            }
          };

          //工作线程
          Thread work = new Thread(new Runnable() {
            @Override
            public void run() {
              String request = (String) selectionKey.attachment(); //获取客户端的请求
              log.info("客服端 消息是: {} ", request);
              consumer.accept("i`m server");
            }
          });
          work.start();
        }
      }
    }
  }

}
